package com.xxh.user.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xxh.common.constant.AuthConstants;
import com.xxh.common.constant.MessageConstants;
import com.xxh.common.constant.PrefixConstants;
import com.xxh.common.utils.BCryptPasswordEncoderUtil;
import com.xxh.common.utils.RedisUtil;
import com.xxh.common.utils.Result;
import com.xxh.common.utils.WebUtils;
import com.xxh.dataaccess.dao.VideoDao;
import com.xxh.dataaccess.dao.recall.UserProfileDao;
import com.xxh.dataaccess.dto.VideoDto;
import com.xxh.dataaccess.entity.*;
import com.xxh.dataaccess.page.MongoPageHelper;
import com.xxh.dataaccess.page.PageResult;
import com.xxh.dataaccess.rpcservice.ClientGrpcService;
import com.xxh.dataaccess.service.*;
import com.xxh.user.mq.MqConfig;
import com.xxh.user.mq.PostMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    @Resource
    BCryptPasswordEncoderUtil bCryptPasswordEncoderUtil;

    @Autowired
    FriendService friendService;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    MongoPageHelper mongoPageHelper;


    @Autowired
    CommentService commentService;

    @Autowired
    VideoDao videoDao;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    UserMessageService userMessageService;

    @Autowired
    UserViewHistoryService userViewHistoryService;


    @Autowired
    RedisUtil redisUtil;

    @Autowired
    ProudService proudService;


    @Autowired
    UserProfileDao userProfileDao;

    @Autowired
    RecallService recallService;


    @GetMapping("/test")
    public String test() {
        return "用户 test";
    }


    /**
     * 注册接口
     */


    @GetMapping("/register")
    public Result Register(@RequestBody(required = true) User user) {
        String encode = bCryptPasswordEncoderUtil.encode(user.getPassword());
        user.setPassword(encode);

        if (user.getUsername().equals("")) {
            return Result.error().put("msg", "用户名不为空");
        }
        if (user.getNickname().equals("")) {
            return Result.error().put("msg", "昵称不为空");
        }
        if (user.getPassword().equals("")) {
            return Result.error().put("msg", "密码不为空");
        }
        String result = userService.insert(user);
        if ("用户名已存在".endsWith(result)) {
            return Result.error().put("msg", result);
        }

        return Result.success().put("msg", result);
    }

    /**
     * 要是不传uid默认就是查自己的信息
     *
     * @param uid 别人的ID
     * @return
     */
    @GetMapping("/getInfo")
    public Result getUserInfo(@RequestParam(value = "uid", required = false) Integer uid) {
        if (uid == null) {
            Long id = WebUtils.getUserId();
            Result result = Result.success();
            User user = userService.getById(id);
            result.put("data", user);
            return result;
        } else {
            User user = userService.getById(uid);
            Result result = Result.success();
            result.put("data", user);
            return result;
        }
    }


    @GetMapping("/getfavVideo")
    public Result getFavVideos(
            @RequestParam(value = "cur", required = false, defaultValue = "1") Integer cur,
            @RequestParam(value = "size", required = false, defaultValue = "20") Integer size) {

        Long userId = WebUtils.getUserId();
        IPage<Video> page = userService.getCollectionByUid(Math.toIntExact(userId), cur, size);
        return Result.success().put("data", page);
    }


    @GetMapping("/getfavMovies")
    public Result getFavMovies(
            @RequestParam(value = "cur", required = false, defaultValue = "1") Integer cur,
            @RequestParam(value = "size", required = false, defaultValue = "20") Integer size
    ) {
        Long userId = WebUtils.getUserId();
        IPage<Movie> page = userService.getMovieCollectionByUid(Math.toIntExact(userId), cur, size);
        return Result.success().put("data", page);
    }

    @GetMapping("/viewHistory")
    public Result getHistory(
            @RequestParam(value = "cur", required = false, defaultValue = "1") Integer cur,
            @RequestParam(value = "size", required = false, defaultValue = "20") Integer size
    ) {
        Long userId = WebUtils.getUserId();
        //先出缓存里拿，缓存有，存入数据库，然后清空缓存
        List<UserviewHistory> list = new ArrayList<>();
        String histroyStr = redisUtil.lRightPop(PrefixConstants.Histroy + userId);
        while (histroyStr != null) {
            UserviewHistory history = JSON.parseObject(histroyStr, UserviewHistory.class);
            list.add(history);
            histroyStr = redisUtil.lRightPop(PrefixConstants.Histroy + userId);
        }
        userViewHistoryService.saveBatch(list);
        redisUtil.delete(PrefixConstants.Histroy + userId);
        IPage<VideoDto> page = userService.gethistoryByUid(Math.toIntExact(userId), cur, size);
        return Result.success().put("data", page);

    }


    //注册接口
    @PostMapping("/register")
    public Result insert(@RequestBody User user) {

        if (user.getUsername().equals("")) {
            return Result.error().put("msg", "用户名不为空");
        }
        if (user.getPassword().equals("")) {
            return Result.error().put("msg", "密码不为空");
        }
        if (user.getNickname().equals("")) {
            return Result.error().put("msg", "昵称不为空");
        }
        User userExist = userService.findByUserName(user.getUsername());
        if (userExist != null) {
            return Result.error().put("msg", AuthConstants.USER_EXIST);
        } else {
            //注册的时候记得BCY加密密码，要不然框架不认明文
            String encodepwd = bCryptPasswordEncoderUtil.encode(user.getPassword());
            user.setPassword(encodepwd);
            if (userService.save(user)) {
                PostMessage postMessage = new PostMessage();
                postMessage.setUser(user);
                //不发邮件了，太麻烦了
                //rabbitTemplate.convertAndSend("xxvideo", MqConfig.EmailKEY, postMessage);
                return Result.success().put("msg", "注册成功");
            } else {
                return Result.error().put("msg", "未知错误");
            }
        }
    }


    //添加好友
    @PostMapping("/addFriend")
    public Result addFriend(@RequestParam(name = "uid", required = true) Integer fid) {
        //获取当前用户
        int uid = Math.toIntExact(WebUtils.getUserId());
        List<Integer> fids = friendService.getFriendID(uid);
        if (fids.contains(fid)) {
            return Result.error().put("msg", "你们已经是好友了");
        } else {
            Friend friend = new Friend();
            friend.setUserId(uid);
            friend.setFriendId(fid);
            friendService.save(friend);
            return Result.success().put("msg", "好友添加成功");
        }
    }


    //查询好友列表
    @GetMapping("/getFriend")
    public Result getFriend(
            @RequestParam(value = "cur", required = false, defaultValue = "1") Integer cur,
            @RequestParam(value = "size", required = false, defaultValue = "20") Integer size) {

        Long uid = WebUtils.getUserId();
        List<Integer> fids = friendService.getFriendID(Math.toIntExact(uid));
        //批量查询出用户信息
        List<User> friends = (List<User>) userService.listByIds(fids);
        return Result.success().put("data", friends);
    }


    @GetMapping("/getFriendStatus")
    public Result friendStatus(@RequestParam(name = "uid", required = true) Integer fid) {
        //获取当前用户
        if (null != WebUtils.getUserId()) {
            int uid = Math.toIntExact(WebUtils.getUserId());
            boolean status = friendService.isFriend(uid, fid);
            return Result.success().put("status", status);
        }
        return Result.success().put("status", false);
    }

    //根据上传用户的用户名获取视频
    @GetMapping("/getVideoByUname")
    public Result getVideoByUpName(@RequestParam(value = "uname", required = false) String username,
                                   @RequestParam(value = "cur", required = false, defaultValue = "1") Integer cur,
                                   @RequestParam(value = "size", required = false, defaultValue = "20") Integer size,
                                   @RequestParam(value = "keyword", required = false) String title) {

        //查自己的上传
        if (null == username) {
            Long userId = WebUtils.getUserId();
            User user = userService.getById(userId);
            Query query = new Query();
            query.addCriteria(Criteria.where("name").is(user.getUsername()));
            //正则实现模糊查询
            if (null != title && "" != title) {

                Pattern pattern = Pattern.compile("^.*" + title + ".*$", Pattern.CASE_INSENSITIVE);
                query.addCriteria(Criteria.where("title").regex(pattern));
            }
            PageResult<Video> page = mongoPageHelper.pageQuery(query, Video.class, size, cur);
            Result result = Result.success();
            result.put("page", page);
            return result;
        } else {
            //查别人的上传视频
            Query query = new Query();
            query.addCriteria(Criteria.where("name").is(username));
            PageResult<Video> page = mongoPageHelper.pageQuery(query, Video.class, size, cur);
            Result result = Result.success();
            result.put("page", page);
            return result;
        }
    }


    //评论视频
    @GetMapping("/commentVideo")
    public Result pubComment(
            @RequestParam(value = "bv", required = true) String bv,
            @RequestParam(value = "content", required = true) String content) {


        //当前用户ID
        Long uid = WebUtils.getUserId();
        //构造评论对象
        Comment comment = new Comment();
        comment.setContent(content);
        comment.setVideoId(bv);
        comment.setUserId(Long.valueOf(uid));
        comment.setCreated(new Date());
        comment.setLevel(0);
        comment.setParentId(0L);
        //评论表插入一条评论
        commentService.insert(comment);


        //更新视频评论数
        Query query = new Query();
        query.addCriteria(Criteria.where("bv").is(bv));
        Video video = mongoTemplate.findOne(query, Video.class);
        video.setReply(video.getReply() + 1);
        videoDao.save(video);
        //返回成功
        return Result.success();

    }


    //评论用户的评论

    /**
     * @param bv
     * @param content
     * @param cid     被评论的评论ID
     * @param toUid   被评论的用户
     * @return
     */
    @PostMapping("/commentUser")
    public Result CommentUser(
            @RequestParam(value = "bv", required = true) String bv,
            @RequestParam(value = "content", required = true) String content,
            @RequestParam(value = "cid", required = true) Long cid,
            @RequestParam(value = "uid", required = true) Long toUid
    ) {
        //当前用户ID
        Long uid = WebUtils.getUserId();
        //构造评论对象
        Comment comment = new Comment();
        comment.setContent(content);
        comment.setVideoId(bv);
        comment.setUserId(uid);
        comment.setTouserId(toUid);
        comment.setParentId(cid);
        comment.setCreated(new Date());
        comment.setLevel(0);
        //评论表插入一条评论
        commentService.save(comment);

        //构造消息对象
        UserMessage userMessage = new UserMessage();
        userMessage.setFromUserId(uid);
        userMessage.setToUserId(toUid);
        userMessage.setVideoId(bv);
        userMessage.setCommentId(cid);
        userMessage.setContent(content);
        userMessage.setType(MessageConstants.MEG_TYPE_REPLY);
        userMessage.setCreated(new Date());
        //消息表插入一条记录
        userMessageService.save(userMessage);


        //socket通知在线的用户
        return Result.success();
    }


    //用户代表作
    @GetMapping("/getProudVideo")
    public Result getProdVideos(@RequestParam(value = "uid", required = false) Long uid) {
        if (uid == null) {
            Long userId = WebUtils.getUserId();
            List<Video> videos = proudService.getProudVideos(userId);
            return Result.success().put("proud", videos);
        } else {
            List<Video> videos = proudService.getProudVideos(uid);
            return Result.success().put("proud", videos);
        }

    }


    //设置视频为我的代表作(最多为3个)
    @GetMapping("/setProudVideo")
    public Result setProdVideos(String bv) {
        Long userId = WebUtils.getUserId();
        if (userId != null) {
            if (proudService.getProudVideos(userId).size() <= 2) {
                proudService.setProudVideos(bv, userId);
                return Result.success();
            } else {
                return Result.error().put("msg", "代表作个数不能超过3个");
            }
        } else {
            return Result.error().put("msg", "请先登录");
        }
    }


    //移除视频为我的代表作
    @DeleteMapping("/removeProudVideo")
    public Result removeProdVideos(String bv) {
        Long userId = WebUtils.getUserId();
        if (userId != null) {
            proudService.removeProudVideos(bv, userId);
            return Result.success();
        } else {
            return Result.error().put("msg", "请先登录");
        }
    }


    //是否为代表作？
    @GetMapping("/IsProudVideo")
    public Result isProdVides(String bv) {
        Long userId = WebUtils.getUserId();
        if (userId != null) {
            boolean b = proudService.isProudVideo(bv, userId);
            return Result.success().put("status", b);
        } else {
            return Result.error().put("msg", "请先登录");
        }
    }

    @GetMapping("/GetUserProfile")
    public Result getUserProfile() {
        Long userId = WebUtils.getUserId();
        if (userId != null) {
            List<UserProfile> profiles = userProfileDao.findByUid(Math.toIntExact(userId));
            return Result.success().put("profiles", profiles);
        } else {
            return Result.error().put("msg", "请先登录");
        }
    }

    //插入用户画像
    @PostMapping("/InsertUserProfile")
    public Result insertUserProfile(@RequestBody ArrayList<String> profiles) {
        Long userId = WebUtils.getUserId();
        ArrayList<UserProfile> list = new ArrayList<>();
        for (String profile : profiles) {
            UserProfile p = new UserProfile();
            p.setProfile(profile);
            p.setUid(Math.toIntExact(userId));
            p.setWeight(1.0);
            list.add(p);
        }
        System.out.println(list);
        //新增用户画像
        userProfileDao.insert(list);
        //调用python的方法，更新该用户的召回集
        recallService.genUserProfileRecallByUid(Math.toIntExact(userId));
        return Result.success();
    }

    @GetMapping("/testGrpc")
    public Result testGrpc() {

        boolean b = recallService.genUserProfileRecallByUid(12);
        return Result.success().put("msg", "success");
    }

}
